package org.yuanqiframework.yuanqi.core.utils.crypto;

import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import lombok.Data;

/**
 * 项目数据加密解密
 * 公钥加密，私钥解密
 * Hutool的AES默认使用CBC模式和PKCS5Padding填充方式
 *
 * @Author 曹波涛
 * @Date 2022/10/31 9:38
 * @Version 1.0
 */
public class RsaUtils {
    @Data
    public static class RsaKeyHolder {
        private String privateKey;
        private String publicKey;
    }

    /**
     * 生成默认长度(1024位)的RSA密钥对
     *
     * @return 包含公钥和私钥的Map，key为"publicKey"和"privateKey"
     */
    public static RsaKeyHolder generateKeyPair() {
        try {
            RSA rsa = new RSA();
            RsaKeyHolder rsaKeyHolder = new RsaKeyHolder();
            rsaKeyHolder.setPrivateKey(rsa.getPrivateKeyBase64());
            rsaKeyHolder.setPublicKey(rsa.getPublicKeyBase64());
            return rsaKeyHolder;
        } catch (Exception e) {
            throw new RuntimeException("生成RSA密钥对失败", e);
        }
    }

    /**
     * 使用指定公钥加密
     *
     * @param data
     * @param publicKey
     * @return
     */
    public static String encryptStr(String data, String publicKey) {
        try {
            RSA rsa = new RSA(null, publicKey);
            return rsa.encryptBase64(data, KeyType.PublicKey);
        } catch (Exception e) {
            throw new RuntimeException("RSA加密失败", e);
        }
    }

    /**
     * 使用指定私钥解密base64
     *
     * @param data
     * @param privateKey
     * @return
     */
    public static String decryptStr(String data, String privateKey) {
        try {
            RSA rsa = new RSA(privateKey, null);
            return rsa.decryptStr(data, KeyType.PrivateKey);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("RSA解密失败", e);
        }
    }

    /**
     * 使用指定密钥对进行加密和解密操作
     *
     * @param data
     * @param privateKey
     * @param publicKey
     * @return
     */
    public static String decryptStr(String data, String privateKey, String publicKey) {
        try {
            RSA rsa = new RSA(privateKey, publicKey);
            return rsa.decryptStr(data, KeyType.PrivateKey);
        } catch (Exception e) {
            throw new RuntimeException("RSA解密失败", e);
        }
    }

    /**
     * 创建新的RSA实例
     *
     * @param privateKey
     * @param publicKey
     * @return
     */
    public static RSA createRsaInstance(String privateKey, String publicKey) {
        try {
            return new RSA(privateKey, publicKey);
        } catch (Exception e) {
            throw new RuntimeException("创建RSA实例失败", e);
        }
    }
}
